package com.heima.admin.service.impl;
 
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.admin.mapper.AdUserMapper;
import com.heima.admin.service.AdUserService;
import com.heima.model.admin.dtos.AdUserDto;
import com.heima.model.admin.pojos.AdUser;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.utils.common.AppJwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
 
import java.util.HashMap;
import java.util.Map;
 
@Service//表明该类是一个业务逻辑层
@Slf4j//记录日志
@Transactional//因为涉及多张表的修改操作，所以需要开启事务
//主要功能是实现管理员端用户的登录验证流程，包括检查用户名和密码是否为空，验证用户是否存在
//比对用户输入的密码和数据库中的密码是否匹配，以及在密码匹配成功后生成并返回一个JWT令牌给客户端，以便后续的请求中进行身份验证
public class AdUserServiceImpl extends ServiceImpl<AdUserMapper, AdUser> implements AdUserService {

    /**
     * 登录
     * @param dto
     * @return
     */
    @Override
    //管理员端用户登录的方法
    public ResponseResult login(AdUserDto dto) {
        // 1. 检查参数，检查传入的AdUserDto对象的name和password字段是否为空或空白字符串
        if(StringUtils.isBlank(dto.getName()) || StringUtils.isBlank(dto.getPassword())) {
            //用户名或者密码有任意一个为空，直接提示参数非法
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "用户名或密码不能为空");
        }
 
        // 2. 查询用户，查找数据库中用户名与dto.getName()相等的AdUser对象
        AdUser user = getOne(Wrappers.<AdUser>lambdaQuery().eq(AdUser::getName, dto.getName()));
        //判断根据用户名从数据库中查询出来的对象是否为空，为空表明数据库中无此人
        if(user == null) {
            //没有此人，直接提示错误，数据不存在
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在");
        }

        //代码运行到此，表明参数不为空并且数据库中有此人，接下来比对密码
        // 3. 比对密码，首先从查询结果中获取用户对象的salt值
        String salt = user.getSalt();
        //从传入的AdUserDto对象中获取密码
        String password = dto.getPassword();
        // md5加密，使用DigestUtils.md5DigestAsHex()方法对密码和salt值进行MD5加密
        //利用salt值是为了增加密码的安全性，防止密码被轻易破解
        password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        //拿着刚刚生成的加密后的密码和数据库中的密码比对
        if(password.equals(user.getPassword())) {
            // 4. 返回数据 - jwt
            //如果用户密码验证成功，创建一个Map对象，用于存放返回给客户端的数据
            Map<String, Object> map = new HashMap<>();
            //使用AppJwtUtil.getToken()方法生成一个JWT（JSON Web Token）
            map.put("token", AppJwtUtil.getToken(user.getId().longValue()));
            //为了安全起见，将用户对象中的salt和password字段清空（即使这些字段之前在数据库查询中被获取）
            user.setSalt("");
            user.setPassword("");
            //将处理后的用户对象放入map中作为user键的值
            map.put("user", user);
            //使用ResponseResult.okResult(map)方法构造一个成功的响应结果对象，并返回给客户端，包含JWT和用户信息
            return ResponseResult.okResult(map);
        } else {
            // 密码错误，如果密码不正确，则返回一个错误响应，错误信息为“密码错误”
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
        }
    }
}